package curd

import (
	"fmt"
	"strings"
)

type ModelField struct {
	Name       string `json:"name"`
	Type       string `json:"type"`
	IsRequired bool   `json:"is_required"` // 生成typings.d.ts 时用
	NotInsert  bool   `json:"not_insert"`  // true -> graphql中不做为插入字段
	NotUpdate  bool   `json:"not_update"`  // true -> graphql中不做为更新字段

	Title          string `json:"title"`            // column 显示的名称
	IsColumn       bool   `json:"is_column"`        // 是否做为column显示在页面上
	IsSearch       bool   `json:"is_search"`        // 是否做为 检索条件
	IsPageRequired bool   `json:"is_page_required"` // 是否页面必须输入项
	PageRequireMsg string `json:"page_require_msg"` // 必须项提示消息
	PageCtrl       string `json:"page_ctrl"`        // 页面显示用的控件
}

type ModelItem struct {
	Name        string       `json:"name"`
	GraphqlName string       `json:"graphql_name"`
	Fields      []ModelField `json:"fields"`
}

type PageItem struct {
	ApiImport string `json:"api_import"`
	Title     string `json:"title"` // 页面的标题
}

type CurdJSON struct {
	Model ModelItem `json:"model"`
	Page  PageItem  `json:"page"`
}

// ==================================
// func for ModelField
// ==================================

// 转换类型 graphql 类型 -> typescript 类型
func (mf ModelField) ConvertTypeForTs() string {
	tsType := ""

	switch mf.Type {
	case "Int":
		fallthrough
	case "Float":
		tsType = "number"
	default:
		tsType = "string"
	}

	return tsType
}

// 生成页面上控件字符串
func (mf ModelField) GenPageCtrl() string {
	var s string

	switch mf.PageCtrl {
	case "text":
		s = GenText(mf)
	case "password":
		// TODO
	case "textarea":
		// TODO
	case "digit":
		// TODO
	case "date":
		// TODO
	case "datetime":
		// TODO
	case "select":
		// TODO
	case "check":
		// TODO
	case "radio":
		s = GenRadio(mf)
	case "switch":
		// TODO
	default:
		s = ""
	}

	return s
}

// ==================================
// func for ModelItem
// ==================================

// graphql 检索时的where条件
func (mi ModelItem) GenGraphqlSearchWhere(isOnly bool) string {
	whereFields := make([]string, 0)
	for _, field := range mi.Fields {

		// TODO: 暂时只有 like 检索
		if field.IsSearch {
			whereFields = append(whereFields, field.Name+": {_ilike: $"+field.Name+"}")
		}
	}

	if len(whereFields) == 0 {
		return ""
	}

	// 只有where 条件，前面没有其他条件
	if isOnly {
		return "where: {" + strings.Join(whereFields, ", ") + "}"
	}

	return ", where: {" + strings.Join(whereFields, ", ") + "}"
}

// graphql 插入时的字段定义列表
func (mi ModelItem) GenGraphqlInsertParamDefinations() string {
	params := make([]string, 0)
	for _, field := range mi.Fields {
		if field.NotInsert {
			continue
		}

		if field.IsPageRequired {
			params = append(params, "$"+field.Name+": "+field.Type+"!")
		} else {
			params = append(params, "$"+field.Name+": "+field.Type)
		}
	}

	if len(params) == 0 {
		return ""
	}

	return strings.Join(params, ", ")
}

// graphql 插入时的字段列表
func (mi ModelItem) GenGraphqlInsertParams() string {
	params := make([]string, 0)
	for _, field := range mi.Fields {
		if field.NotInsert {
			continue
		}
		params = append(params, field.Name+": $"+field.Name)
	}

	if len(params) == 0 {
		return ""
	}

	return strings.Join(params, ", ")
}

// graphql 更新时的字段定义列表
func (mi ModelItem) GenGraphqlUpdateParamDefinations() string {
	params := make([]string, 0)
	for _, field := range mi.Fields {
		if field.NotUpdate {
			continue
		}

		params = append(params, "$"+field.Name+": "+field.Type)
	}

	if len(params) == 0 {
		return ""
	}

	return strings.Join(params, ", ")
}

// graphql 更新时的字段列表
func (mi ModelItem) GenGraphqlUpdateParams() string {
	params := make([]string, 0)
	for _, field := range mi.Fields {
		if field.NotUpdate {
			continue
		}
		params = append(params, field.Name+": $"+field.Name)
	}

	if len(params) == 0 {
		return ""
	}

	return strings.Join(params, ", ")
}

// 需要引入的控件
// 支持的控件类型：text -> ProFormText;
//                 password -> ProFormPassword
//                 textarea -> ProFormTextArea
//                 digit -> ProFormDigit
//                 date -> ProFormDatePicker
//                 datetime -> ProFormDateTimePicker
//                 select -> ProFormSelect
//                 check -> ProFormCheckbox
//                 radio -> ProFormRadio
//                 switch -> ProFormSwitch
func (mi ModelItem) GenPageImportCtrls() string {
	m := make(map[string]bool)

	for _, field := range mi.Fields {
		switch field.PageCtrl {
		case "text":
			m["ProFormText"] = true
		case "password":
			m["ProFormPassword"] = true
		case "textarea":
			m["ProFormTextArea"] = true
		case "digit":
			m["ProFormDigit"] = true
		case "date":
			m["ProFormDatePicker"] = true
		case "datetime":
			m["ProFormDateTimePicker"] = true
		case "select":
			m["ProFormSelect"] = true
		case "check":
			m["ProFormCheckbox"] = true
		case "radio":
			m["ProFormRadio"] = true
		case "switch":
			m["ProFormSwitch"] = true
		default:
			m["ProFormText"] = true
		}
	}

	keys := make([]string, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}

	return fmt.Sprintf(`{ %s } from '@ant-design/pro-form';`, strings.Join(keys, ", "))
}
